package cn.wdm.ymcc.service.impl;

import cn.wdm.ymcc.CourseDoc;
import cn.wdm.ymcc.dto.CourseDetailInfoDto;
import cn.wdm.ymcc.feign.MediaFeignClient;
import cn.wdm.ymcc.feign.SendEmailFeignClient;
import cn.wdm.ymcc.domain.*;
import cn.wdm.ymcc.dto.CourseDto;
import cn.wdm.ymcc.feign.SearchFeignClient;
import cn.wdm.ymcc.mapper.CourseMapper;
import cn.wdm.ymcc.result.JSONResult;
import cn.wdm.ymcc.service.*;
import cn.wdm.ymcc.util.AssertUtil;
import cn.wdm.ymcc.util.StrUtils;
import cn.wdm.ymcc.vo.CourseItemVo;
import cn.wdm.ymcc.vo.CourseOrderVo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lao.zhang
 * @since 2022-07-21
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
    @Autowired
    private ICourseService courseService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseSummaryService courseSummaryService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private ICourseChapterService courseChapterService;
    //注入的feign接口
    @Autowired
    private SearchFeignClient searchFeignClient;
    @Autowired
    private SendEmailFeignClient sendEmailFeignClient;
    @Autowired
    private MediaFeignClient mediaFeignClient;

    /**
     * 录入课程
     * 1.参数校验 JSR303
     * 2.课程不能已经存在
     * 3.新增课程相关的表
     * @param dto
     */
    @Override
    public void saveCourse(CourseDto dto) {
        Course course = dto.getCourse();
        CourseDetail courseDetail = dto.getCourseDetail();
        CourseMarket courseMarket = dto.getCourseMarket();
        CourseResource courseResource = dto.getCourseResource();
        List<Long> teacharIds = dto.getTeacharIds();
        //1.参数校验 JSR303
        //2.课程不能已经存在，根据课程名字取查询是否存在
        //Wrapper<Block> tWrapper = new EntityWrapper();
        Wrapper<Course> wrapper = new EntityWrapper<>();
        wrapper.eq("name",course.getName());
        Course courseInMysql = selectOne(wrapper);
        AssertUtil.isNull(courseInMysql,"课程已经存在");
        //3.新增相关的表
//         3.1 保存课程
        course.setStatus(0);
        course.setLoginId(1L);
        course.setLoginUserName("yhptest1");
        //获取讲师的名字，并且保存在课程表中
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);
        StringBuilder sb = new StringBuilder();
        for (Teacher teacher : teachers) {
            sb.append(teacher.getName()).append(",");
        }
        course.setTeacherNames(sb.toString());
        insert(course);
//         3.2 保存课程销售
        //与course的Id一致
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);
//         3.3 保存课程详情
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);
//         3.4 保存课程讲师
        CourseTeacher courseTeacher = new CourseTeacher();
        for (Long teacharId : teacharIds) {
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(teacharId);
            courseTeacherService.insert(courseTeacher);
        }
//         3.5 保存课程资源
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);
//         3.6 初始化课程统计
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);
        //3.7 课程类型表中的课程数+1
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        type.setTotalCount(type.getTotalCount() + 1);
        courseTypeService.updateById(type);
    }

    /**
     * 课程发布上线
     * @param courseId
     */
    @Override
    public void onLineCourse(Long courseId) {
//        1.根据课程Id查询课程，判断是否存在
        Course course = courseService.selectById(courseId);
        AssertUtil.isNotNull(course,"课程不存在");
        AssertUtil.isFalse(course.getStatus()==1,"该课程已经下线，不能重复下线");
//        2.修改课程状态为上架，填写上架时间
        course.setStatus(1);
        updateById(course);
//        * 3.保存课程相关内容到Es
//        3.1 为service-search编写feign接口 ymcc-api-search
//        3.2 在课程微服务中，依赖ymcc-api-search
//        3.3 使用feign远程调用search完成课程保存到Es中
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = getCourseSummary(courseId);
        CourseDoc doc = new CourseDoc();
        //设置需要保存到Es的字段
        BeanUtils.copyProperties(course,doc);
        BeanUtils.copyProperties(courseMarket,doc);
        BeanUtils.copyProperties(courseSummary,doc);
        doc.setCourseTypeName(type.getName());//这里要单独赋值
        String chargeName = courseMarket.getCharge() == 1 ? "免费" : "收费";
        doc.setChargeName(chargeName);
        JSONResult result = searchFeignClient.savaCourse2Es(doc);
        AssertUtil.isTrue(result.isSuccess(),"课程发布失败");
        //4.课程消息推送，课程发布成功往MQ异步的去推送消息。公共的微服务做消息的推送。发送简单的课程消息到MQ。
        MessageEmail messageEmail = new MessageEmail();
        messageEmail.setTitle("新增课程啦！");
        messageEmail.setContent("新增的课程要来看一下吗？--"+course.getName());
        messageEmail.setSendTime(new Date());
        sendEmailFeignClient.sendMsg(messageEmail);
    }
    /**
     * 课程下架
     * @param courseId
     */
    @Override
    @Transactional
    public void offLineCourse(Long courseId) {
        //1.修改状态
        Course course = courseService.selectById(courseId);
        AssertUtil.isNotNull(course,"课程不存在");
        AssertUtil.isFalse(course.getStatus()==0,"该课程已经上线，不能重复上线");
        course.setStatus(0);
        updateById(course);
        //2.删除es中的课程
        JSONResult jsonResult = searchFeignClient.deleteCourseInEs(courseId);
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程下架失败");
    }

    /**
     * 获取课程的详情
     * @param courseId
     * @return
     */
    @Override
    public JSONResult getCourseDeatis(Long courseId) {
        AssertUtil.isNotNull(courseId,"参数为空courseId");
//1.获取课程
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"参数为空Course");
        boolean onLine = course.getStatus() == 1;
        AssertUtil.isTrue(onLine,"请求非法");//课程没有上线
//2.获取详情
        CourseDetail courseDetail = getCourseDetail(courseId);
        AssertUtil.isNotNull(courseDetail,"参数为空courseDetail");
//3.获取课程的费用信息
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        AssertUtil.isNotNull(courseMarket,"参数为空courseMarket");
//4.获取课程统计相关
        CourseSummary courseSummary = getCourseSummary(courseId);
        AssertUtil.isNotNull(courseSummary,"参数为空courseSummary");
//5.获取课程的老师
        List<Teacher> teachers = getTeachers(courseId);
//6.查询课程的章节及其章节下面的视频，一个章节有多个视频
        List<CourseChapter> courseChapters = getCourseChapters(courseId);
//7.获取课程
        CourseDetailInfoDto courseDetailInfoDto = getCourseDetailInfoDto(course, courseDetail, courseMarket, courseSummary, teachers, courseChapters);
        return JSONResult.success(courseDetailInfoDto);
    }

    /**
     * 用于结算页的数据的回显
     * @param courseIds
     * @return
     */
    @Override
    public JSONResult getCourseInfos(String courseIds) {
        AssertUtil.isNotNull(courseIds,"courseIds为空");
        List<Long> ids = StrUtils.splitStr2LongArr(courseIds);
        //1.去重复
        Set<Long> setIds = ids.stream().collect(Collectors.toSet());
        //2.业务校验
        boolean ok = setIds.size() == ids.size();
        AssertUtil.isTrue(ok,"请求非法");
        //2.查询参数
        ArrayList<CourseItemVo> courseItemVos = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal(0);
        for (Long setId : setIds) {
            //2.1查询课程
            Course course = selectById(setId);
            AssertUtil.isNotNull(course,"course为空");
            //判断是否上线的课程
            boolean onLine = course.getStatus() == 1;
            AssertUtil.isTrue(onLine,"该课程不存在offLine");
            //2.2查询课程相关价格
            CourseMarket courseMarket = courseMarketService.selectById(setId);
            AssertUtil.isNotNull(courseMarket,"courseMarket为空");

            CourseItemVo courseItemVo = new CourseItemVo(course, courseMarket);
            courseItemVos.add(courseItemVo);
            totalAmount=totalAmount.add(courseMarket.getPrice());
        }
        //2.3封装数据返回
        CourseOrderVo courseOrderVo = new CourseOrderVo(courseItemVos, totalAmount);
        return JSONResult.success(courseOrderVo);
    }

    //------------------------抽出的方法开始-----------------------------------
    private CourseDetailInfoDto getCourseDetailInfoDto(Course course, CourseDetail courseDetail, CourseMarket courseMarket, CourseSummary courseSummary, List<Teacher> teachers, List<CourseChapter> courseChapters) {
        CourseDetailInfoDto courseDetailInfoDto = new CourseDetailInfoDto();
        courseDetailInfoDto.setCourse(course);
        courseDetailInfoDto.setCourseChapters(courseChapters);
        courseDetailInfoDto.setCourseMarket(courseMarket);
        courseDetailInfoDto.setCourseSummary(courseSummary);
        courseDetailInfoDto.setCourseDetail(courseDetail);
        courseDetailInfoDto.setTeachers(teachers);
        return courseDetailInfoDto;
    }
    private List<CourseChapter> getCourseChapters(Long courseId) {
        EntityWrapper<CourseChapter> wrapper1 = new EntityWrapper<>();
        wrapper1.eq("course_id", courseId);
        List<CourseChapter> courseChapters = courseChapterService.selectList(wrapper1);
        //调用mediaFeign去获取章节的视频，把每个章节的视频放到对应的章节下面。mediaFeignClient
        courseChapters.forEach(courseChapter -> {
            JSONResult jsonResult = mediaFeignClient.getMediasByChapterId(courseChapter.getId());
            if(jsonResult.isSuccess()&&jsonResult.getData()!=null){
                List<MediaFile> mediaFiles = JSONObject.parseArray(jsonResult.getData().toString(), MediaFile.class);
                mediaFiles.forEach(mediaFile -> mediaFile.setFileUrl(null));
                courseChapter.getMediaFiles().addAll(mediaFiles);
            }
        });
        return courseChapters;
    }
    private CourseSummary getCourseSummary(Long courseId) {
        return courseSummaryService.selectById(courseId);
    }
    private CourseDetail getCourseDetail(Long courseId) {
        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        return courseDetail;
    }
    private List<Teacher> getTeachers(Long courseId) {
        Wrapper<CourseTeacher> wrapper=new EntityWrapper<CourseTeacher>();
        wrapper.eq("course_id", courseId);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(wrapper);
        List<Long> teacherIds = courseTeachers.stream().map(courseTeacher -> courseTeacher.getTeacherId()).collect(Collectors.toList());
        List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);
        return teachers;
    }
//---------------------------抽出的方法结束------------------------------------
}
